#include <stddef.h>

#ifndef KINECT_STUBS_H
#define KINECT_STUBS_H

#define S_OK                              0LL
#define E_POINTER                         1LL
#define E_INVALIDARG                      2LL       
#define E_NUI_FEATURE_NOT_INITIALIZED     3LL
#define E_FAIL                            4LL
#define E_NUI_IMAGE_STREAM_IN_USE         5LL
#define E_OUTOFMEMORY                     6LL

#define NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX 0x00000001
#define NUI_INITIALIZE_FLAG_USES_COLOR                  0x00000002
#define NUI_INITIALIZE_FLAG_USES_SKELETON               0x00000008  
#define NUI_INITIALIZE_FLAG_USES_DEPTH                  0x00000020
#define NUI_INITIALIZE_DEFAULT_HARDWARE_THREAD          0xFFFFFFFF

//#define E_NUI_DEVICE_NOT_CONNECTED  __HRESULT_FROM_WIN32(ERROR_DEVICE_NOT_CONNECTED)
//#define E_NUI_DEVICE_NOT_READY      __HRESULT_FROM_WIN32(ERROR_NOT_READY)
//#define E_NUI_ALREADY_INITIALIZED   __HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED)
//#define E_NUI_NO_MORE_ITEMS         __HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)
#define FACILITY_NUI 0x301
//#define E_NUI_FRAME_NO_DATA                     MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NUI, 1)
//#define E_NUI_STREAM_NOT_ENABLED                MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NUI, 2)
//#define E_NUI_FRAME_LIMIT_EXCEEDED              MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NUI, 4)
//#define E_NUI_DATABASE_NOT_FOUND                MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NUI, 13)
//#define E_NUI_DATABASE_VERSION_MISMATCH         MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NUI, 14)

#define NUI_SKELETON_QUALITY_CLIPPED_RIGHT  0x00000001
#define NUI_SKELETON_QUALITY_CLIPPED_LEFT   0x00000002
#define NUI_SKELETON_QUALITY_CLIPPED_TOP    0x00000004
#define NUI_SKELETON_QUALITY_CLIPPED_BOTTOM 0x00000008

#define NUI_SKELETON_COUNT 6
#define NUI_SKELETON_MAX_TRACKED_COUNT 2
#define NUI_SKELETON_INVALID_TRACKING_ID 0

#define NUI_SKELETON_FRAME_FLAG_CAMERA_MOTION       0x00000001
#define NUI_SKELETON_FRAME_FLAG_EXTRAPOLATED_FLOOR  0x00000002
#define NUI_SKELETON_FRAME_FLAG_UPPER_BODY_SKELETON 0x00000004
#define NUI_SKELETON_TRACKING_FLAG_SUPPRESS_NO_FRAME_DATA 0x00000001
#define NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 0
#define NUI_CAMERA_SKELETON_TO_DEPTH_IMAGE_MULTIPLIER_320x240 0

#define MAX_MULTIPLE_KINECTS 8

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef float               FLOAT;
typedef FLOAT               *PFLOAT;
typedef BOOL                *PBOOL;
typedef BOOL                *LPBOOL;
typedef BYTE                *PBYTE;
typedef BYTE                *LPBYTE;
typedef int                 *PINT;
typedef int                 *LPINT;
typedef WORD                *PWORD;
typedef WORD                *LPWORD;
typedef long                *LPLONG;
typedef DWORD               *PDWORD;
typedef DWORD               *LPDWORD;
typedef void                *LPVOID;
typedef const void          *LPCVOID;
typedef unsigned int        *UINT;
typedef int                 HRESULT;
typedef void                VOID;
typedef long                LONG;
typedef long long           LONGLONG;
typedef unsigned long       HANDLE;
typedef unsigned short      USHORT;
typedef char*               LPCTSTR;


typedef struct _SECURITY_ATTRIBUTES {
  DWORD  nLength;
  LPVOID lpSecurityDescriptor;
  BOOL   bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;

typedef union _LARGE_INTEGER {
  struct {
    DWORD LowPart;
    LONG  HighPart;
  } ;
  struct {
    DWORD LowPart;
    LONG  HighPart;
  } u;
  LONGLONG QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
  
typedef struct _Vector4
{
  union
  {
    float        vector4_f32[4];
    unsigned int vector4_u32[4];
    struct
    {
      FLOAT x;
      FLOAT y;
      FLOAT z;
      FLOAT w;
    };
    FLOAT v[4];
    UINT  u[4];
  };
} Vector4;

typedef const Vector4 FVector4;

namespace MsrNui
{
  
  typedef enum _NUI_PROPSINDEX
  {
    INDEX_UNIQUE_DEVICE_NAME = 0,
    INDEX_LAST // don't use!
  } NUI_PROPSINDEX;
  
  typedef enum _NUI_PROPSTYPE
  {
    PROPTYPE_UNKNOWN = 0,   // don't use
    PROPTYPE_UINT,      // no need to return anything smaller than an int
    PROPTYPE_FLOAT,
    PROPTYPE_BSTR,      // returns new BSTR. Use SysFreeString( BSTR )when you're done
    PROPTYPE_BLOB
  } NUI_PROPSTYPE;
  
  typedef struct _NUI_PROPTYPEANDSIZE
  {
    NUI_PROPSINDEX index;
    NUI_PROPSTYPE  type;
    size_t         size;
  } NUI_PROPTYPEANDSIZE;
  
  static const NUI_PROPTYPEANDSIZE g_spNuiPropsType [] =
  {
    { INDEX_UNIQUE_DEVICE_NAME,   PROPTYPE_BSTR, sizeof( HANDLE ) },
  };
  
}; // namespace MsrNui

struct INuiInstance{
};

typedef enum _NUI_SKELETON_POSITION_INDEX
{
  NUI_SKELETON_POSITION_HIP_CENTER = 0,
  NUI_SKELETON_POSITION_SPINE,
  NUI_SKELETON_POSITION_SHOULDER_CENTER,
  NUI_SKELETON_POSITION_HEAD,
  NUI_SKELETON_POSITION_SHOULDER_LEFT,
  NUI_SKELETON_POSITION_ELBOW_LEFT,
  NUI_SKELETON_POSITION_WRIST_LEFT,
  NUI_SKELETON_POSITION_HAND_LEFT,
  NUI_SKELETON_POSITION_SHOULDER_RIGHT,
  NUI_SKELETON_POSITION_ELBOW_RIGHT,
  NUI_SKELETON_POSITION_WRIST_RIGHT,
  NUI_SKELETON_POSITION_HAND_RIGHT,
  NUI_SKELETON_POSITION_HIP_LEFT,
  NUI_SKELETON_POSITION_KNEE_LEFT,
  NUI_SKELETON_POSITION_ANKLE_LEFT,
  NUI_SKELETON_POSITION_FOOT_LEFT,
  NUI_SKELETON_POSITION_HIP_RIGHT,
  NUI_SKELETON_POSITION_KNEE_RIGHT,
  NUI_SKELETON_POSITION_ANKLE_RIGHT,
  NUI_SKELETON_POSITION_FOOT_RIGHT,
  NUI_SKELETON_POSITION_COUNT
} NUI_SKELETON_POSITION_INDEX;

typedef struct _NUI_TRANSFORM_SMOOTH_PARAMETERS {
  FLOAT fSmoothing;
  FLOAT fCorrection;
  FLOAT fPrediction;
  FLOAT fJitterRadius;
  FLOAT fMaxDeviationRadius;
} NUI_TRANSFORM_SMOOTH_PARAMETERS;

typedef enum _NUI_SKELETON_POSITION_TRACKING_STATE
{
  NUI_SKELETON_POSITION_NOT_TRACKED = 0,
  NUI_SKELETON_POSITION_INFERRED,
  NUI_SKELETON_POSITION_TRACKED
} NUI_SKELETON_POSITION_TRACKING_STATE;

typedef enum _NUI_SKELETON_TRACKING_STATE
{
  NUI_SKELETON_NOT_TRACKED = 0,
  NUI_SKELETON_POSITION_ONLY,
  NUI_SKELETON_TRACKED
} NUI_SKELETON_TRACKING_STATE;

typedef struct _NUI_SKELETON_DATA
{
  NUI_SKELETON_TRACKING_STATE eTrackingState;
  DWORD dwTrackingID;
  DWORD dwEnrollmentIndex;
  DWORD dwUserIndex;
  Vector4 Position;
  Vector4 SkeletonPositions[NUI_SKELETON_POSITION_COUNT];
  NUI_SKELETON_POSITION_TRACKING_STATE eSkeletonPositionTrackingState[NUI_SKELETON_POSITION_COUNT];
  DWORD dwQualityFlags;
} NUI_SKELETON_DATA;

const DWORD NuiSkeletonDataSize = sizeof(NUI_SKELETON_DATA);

typedef struct _NUI_SKELETON_FRAME
{
  LARGE_INTEGER         liTimeStamp;
  DWORD                 dwFrameNumber;
  DWORD                 dwFlags;
  Vector4              vFloorClipPlane;
  Vector4              vNormalToGravity;
  NUI_SKELETON_DATA     SkeletonData[NUI_SKELETON_COUNT];
} NUI_SKELETON_FRAME;

typedef enum {
  NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX = 0,
  NUI_IMAGE_TYPE_COLOR,
  NUI_IMAGE_TYPE_COLOR_YUV,
  NUI_IMAGE_TYPE_COLOR_RAW_YUV,
  NUI_IMAGE_TYPE_DEPTH,
  NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX_IN_COLOR_SPACE,
  NUI_IMAGE_TYPE_DEPTH_IN_COLOR_SPACE,
  NUI_IMAGE_TYPE_COLOR_IN_DEPTH_SPACE,
} NUI_IMAGE_TYPE;

typedef enum {
  NUI_IMAGE_RESOLUTION_INVALID = -1,
  NUI_IMAGE_RESOLUTION_80x60 = 0,
  NUI_IMAGE_RESOLUTION_320x240,
  NUI_IMAGE_RESOLUTION_640x480,
  NUI_IMAGE_RESOLUTION_1280x1024,
} NUI_IMAGE_RESOLUTION;

typedef struct _KINECT_LOCKED_RECT{
  int    Pitch;
  void * pBits;
} KINECT_LOCKED_RECT;

typedef struct _KINECT_SURFACE_DESC {
  UINT    Width;
  UINT    Height;
} KINECT_SURFACE_DESC;

struct NUI_IMAGE_VIEW_AREA {
  int eDigitalZoom_NotUsed;
  LONG lCenterX_NotUsed;
  LONG lCenterY_NotUsed;
};

class NuiImageBuffer;

struct NUI_IMAGE_FRAME {
  LARGE_INTEGER liTimeStamp;
  DWORD dwFrameNumber;
  NUI_IMAGE_TYPE eImageType;
  NUI_IMAGE_RESOLUTION eResolution;
  NuiImageBuffer *pFrameTexture;
  DWORD dwFrameFlags_NotUsed;
  NUI_IMAGE_VIEW_AREA ViewArea_NotUsed;
};

class NuiImageBuffer{
  int     m_Width;
  int     m_Height;
  int     m_BytesPerPixel;
  
  BYTE *  m_pBuffer;
  
public:
  int BufferLen(){return 0;}
  int Pitch( ){return 0;}
  
  HRESULT LockRect( UINT Level, KINECT_LOCKED_RECT* pLockedRect,const KINECT_LOCKED_RECT* pRectUsuallyNull,DWORD Flags);
  HRESULT GetLevelDesc( UINT Level, KINECT_SURFACE_DESC *pDesc );
  HRESULT UnlockRect( UINT Level);
};


HRESULT NuiImageStreamOpen(NUI_IMAGE_TYPE eImageType, NUI_IMAGE_RESOLUTION eResolution, DWORD dwImageFrameFlags_NotUsed, DWORD dwFrameLimit, HANDLE hNextFrameEvent, HANDLE *phStreamHandle);

HRESULT NuiImageStreamReleaseFrame(HANDLE hStream, const NUI_IMAGE_FRAME *pImageFrame);

HRESULT NuiImageStreamGetNextFrame(HANDLE hStream,DWORD dwMillisecondsToWait,const NUI_IMAGE_FRAME **ppcImageFrame);

HRESULT  NuiInitialize( DWORD dwFlags );

VOID NuiShutdown();

bool MSR_NuiGetPropsBlob( MsrNui::NUI_PROPSINDEX Index, void * pBlob, DWORD * pdwInOutSize );

MsrNui::NUI_PROPSTYPE MSR_NuiGetPropsType( MsrNui::NUI_PROPSINDEX Index );

HRESULT MSR_NUIGetDeviceCount( int * pCount );

HRESULT MSR_NuiCreateInstanceByIndex( int Index, INuiInstance ** ppInstance );

void MSR_NuiDestroyInstance( INuiInstance * pInstance );

HRESULT NuiSkeletonTrackingEnable(HANDLE hNextFrameEvent, DWORD  dwFlags);

HRESULT NuiSkeletonTrackingDisable();

HRESULT NuiCameraElevationGetAngle(LONG* angle);

HRESULT NuiSkeletonGetNextFrame(DWORD dwMillisecondsToWait, NUI_SKELETON_FRAME *pSkeletonFrame);

HRESULT NuiTransformSmooth(NUI_SKELETON_FRAME *pSkeletonFrame, const NUI_TRANSFORM_SMOOTH_PARAMETERS *pSmoothingParams);

VOID NuiTransformSkeletonToDepthImageF(Vector4 vPoint, float *pfDepthX, float *pfDepthY, USHORT *pusDepthValue);

VOID NuiTransformSkeletonToDepthImageF(Vector4 vPoint, FLOAT *pfDepthX, FLOAT *pfDepthY);

Vector4 NuiTransformDepthImageToSkeletonF(float fDepthX, float fDepthY, USHORT usDepthValue);

HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName);

#endif //KINECT_STUBS_H